package com.common.service;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

import org.springframework.util.CollectionUtils;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.common.api.model.PageModel;
import com.common.util.BeanCopyUtil;
import com.github.pagehelper.Page;

/**
 * 服务层公共抽象类
 * <p>
 * 目前版本主要提供对象转换功能，屏蔽服务实现层对具体数据拷贝框架的依赖
 * </p>
 * <p>
 * 接口上的泛型P 表示Po ，D表示Dto
 * </p>
 * 
 * @author ficus
 * @version 0.0.1, 2018-08-30
 * @since 0.0.1
 */
public abstract class BaseService<P, D,Mapper extends BaseMapper<P> > extends ServiceImpl<Mapper,P>{
	
    protected PageModel<D> convertToPageBean(Page<P> page) {
        if (page == null || page.getResult() == null) {
            return new PageModel<D>(new ArrayList<D>(), 0L);
        }
        List<D> result = convertToDto(page.getResult()); 
        return new PageModel<D>(result, page.getTotal());
    }
    
    protected D convertToDto(P po) {
    	D d = convertToDto(po,null);
        return d;
    }

    protected List<D> convertToDto(List<P> po) {
    	List<D>  result=new ArrayList<>();
    	if(CollectionUtils.isEmpty(po)) {
    		return result;
    	}
    	Class<?> dcalss=getGenericClass();
    	for (P p : po) {
			if(p==null) {
				continue ;
			}
			D d=convertToDto(p,dcalss);
			result.add(d);
		}
    	return result;
    }

    protected P convertToPo(D dto) {
    	return convertToPo(dto,null);
    }

    protected List<P> convertToPo(List<D> dto) {
    	List<P>  result=new ArrayList<>();
    	if(CollectionUtils.isEmpty(dto)) {
    		return result;
    	}
    	Class<?> pcalss=getPoGenericClass();
    	for (D d : dto) {
			if(d==null) {
				continue ;
			}
			P p=convertToPo(d,pcalss);
			result.add(p);
		}
    	return result;
    }

    protected Class<?> getGenericClass() {
    	Type t=getClass().getGenericSuperclass();
    	while(t instanceof Class) {
    		Class<?> cc=(Class<?>) t;
			t=cc.getGenericSuperclass();    	
    	}
        Type[] params = ((ParameterizedType)t).getActualTypeArguments();
        return (Class<?>)params[1];
    }

    protected Class<?> getPoGenericClass() {
    	Type t=getClass().getGenericSuperclass();
    	while(t instanceof Class) {
    		Class<?> cc=(Class<?>) t;
			t=cc.getGenericSuperclass();    	
    	}
        Type[] params = ((ParameterizedType)t).getActualTypeArguments();
        return (Class<?>)params[0];
    }

    protected <S, T> T convert(S from, Class<T> to) {
        return BeanCopyUtil.map(from, to);
    }

    protected <S, T> List<T> convertList(Iterable<S> from, Class<T> to) {
        return BeanCopyUtil.mapList(from, to);
    }
    
    @SuppressWarnings("unchecked")
	protected D convertToDto(P po,Class<?> dcalss) {
        if (po == null) {
            return null;
        }
        if(dcalss==null) {
        	dcalss=getGenericClass();
        }
        D dto=(D)BeanCopyUtil.map(po, dcalss);
        return dto;
    }
    
    @SuppressWarnings("unchecked")
	protected P convertToPo(D dto,Class<?> pcalss) {
        if (dto == null) {
            return null;
        }
        if(pcalss==null) {
        	pcalss=getPoGenericClass();
        }
        return (P)BeanCopyUtil.map(dto, pcalss);
    }
}
